﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Http;
using Asxsyd92Core.Utils;

namespace Asxsyd92Core.WeixinUtils.Utility.Core
{


    public class JSSDK
    {   

        private string appId;
        private string appSecret;
        private bool _debug;
        private SimpleCacheProvider _cache;
        public IHttpContextAccessor httpContext;
        const string URL_FORMAT_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
        //  const string URL_FORMAT_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
        const string URL_FORMAT_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi";
        //https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi
        const string CACHE_TOKEN_KEY = "CACHE_TOKEN_KEY";
        const string CACHE_TICKET_KEY = "CACHE_TICKET_KEY";

        const string ISOLLOW = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}";
        const string USERLIST = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={0}&next_openid={1}";
        const string TemplateMSG = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={0}";
        const string USERLISTS = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token={0}";

        //根据appid，secret，code获取微信openid、access token信息
        public OAuth_Token Get_token(string Code)
        {
            //获取微信回传的openid、access token
            string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + Code + "&grant_type=authorization_code");
            //微信回传的数据为Json格式，将Json格式转化成对象
            OAuth_Token Oauth_Token_Model = JsonConvert.DeserializeObject<OAuth_Token>(Str);
            return Oauth_Token_Model;
        }

        //刷新Token(好像这个刷新Token没有实际作用)
        public OAuth_Token refresh_token(string REFRESH_TOKEN)
        {
            string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + appId + "&grant_type=refresh_token&refresh_token=" + REFRESH_TOKEN);
            OAuth_Token Oauth_Token_Model = JsonConvert.DeserializeObject<OAuth_Token>(Str);
            return Oauth_Token_Model;
        }


        //根据openid，access token获得用户信息
        public OAuthUser Get_UserInfo(string REFRESH_TOKEN, string OPENID)
        {
            string Str = GetJson("https://api.weixin.qq.com/sns/userinfo?access_token=" + REFRESH_TOKEN + "&openid=" + OPENID + "&lang=zh_CN");
           
            OAuthUser OAuthUser_Model =JsonConvert.DeserializeObject<OAuthUser>(Str); //JsonHelper.ParseFromJson<OAuthUser>(Str);
            return OAuthUser_Model;
        }
        public User_info_list GetUeserList(List<User_List> os)
        {
         //   Tools.createFile("获取用户信息" + os.Count);
            try
            {
                var token = this._cache.GetCache(CACHE_TOKEN_KEY);
                token = null;
                if (token == null)
                {
                    token = GetAccessToken();
                }
                var da = JsonConvert.SerializeObject(os);
                string Str = HttpHelper.HttpPost(string.Format(USERLISTS, token), da.ToString());
              //  Tools.createFile(Str);
                User_info_list userlist = JsonConvert.DeserializeObject<User_info_list>(Str);// JsonHelper.ParseFromJson<User_info_list>(Str);
              //  Tools.createFile(Str);
                return userlist;
            }
            catch (Exception ex) {
                Asxsyd92Core.Utils.Tools.createFile(ex.Message);
                return null;
            }
        }

        //访问微信url并返回微信信息
        protected string GetJson(string url)
        {
            WebClient wc = new WebClient();
            wc.Credentials = CredentialCache.DefaultCredentials;
            wc.Encoding = Encoding.UTF8;
            string returnText = wc.DownloadString(url);

            if (returnText.Contains("errcode"))
            {
                //可能发生错误
            }
            return returnText;
        }
        /// <summary>
        /// 构建JDK对象
        /// </summary>
        /// <param name="appId">微信公众账号的AppId</param>
        /// <param name="appSecret">公众账号的appSecret</param>
        /// <param name="debug">是否调试</param>
        public JSSDK(string appId, string appSecret, bool debug = false)
        {
            this.appId = appId;
            this.appSecret = appSecret;
            this._cache = SimpleCacheProvider.GetInstance();
            this._debug = debug;
        }


        /// <summary>
        /// 发送模板消息
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="prizename">产品名称</param>
        /// <param name="date">中奖时间</param>
        /// <param name="note">说名</param>
        /// <returns></returns>
        public string SendTemplateMessage(string title, string prizename, string date, string note, string url, string toUserId,string temp)
        {
            var token = this._cache.GetCache(CACHE_TOKEN_KEY);
            token = null;
            if (token == null)
            {
                token = GetAccessToken();
            }
            var data = new TemplateModel(title, prizename, date, note);
           data.touser = toUserId;
           data.template_id = temp;
           data.url = url;
           data.topcolor = "#ff0000";
          return  SendMessage(token.ToString(),data);
        
        }
        public string SendMessage(string token, TemplateModel model)
        {
          
         return  HttpHelper.HttpPost(string.Format(TemplateMSG, token), JsonConvert.SerializeObject( model).ToString());
    

        } 
        /// <summary>
        /// 生成签名的随机字符串
        /// </summary>
        /// <param name="length">长度，小于32位，默认16位</param>
        /// <returns>随机字符串</returns>
        private string CreateNonceStr(int length = 16)
        {
            return Guid.NewGuid().ToString().Replace("-", "").Substring(0, length > 32 ? 32 : length);
        }
        /// <summary>
        /// 获取用户列表NestOpenid为""时默认重头开始获取，传入下一个用户NextOpenid
        /// </summary>
        /// <returns>NextOpenid</returns>
        public WXUserList GetWXUserList(string NextOpenid)
        {
            var token = this._cache.GetCache(CACHE_TOKEN_KEY);
            token = null;
            if (token == null)
            {
                token = GetAccessToken();
            }
        
            string result = HttpGet(string.Format(USERLIST, token, NextOpenid));
            return JsonConvert.DeserializeObject<WXUserList>(result);
            //return serializer.Deserialize<WXUserList>(result); //反序列化：JSON字符串=>对象
                
        }
        /// <summary>
        /// 判断是否关注微信平台
        /// </summary>
        /// <returns>AccessToken</returns>
        public bool IsFollow(string userappId)
        {



            var token = this._cache.GetCache(CACHE_TOKEN_KEY);
            token = null;
            if (token == null)
            {
               token= GetAccessToken();
            }
            try
            {
                string result = HttpHelper.HttpGet(string.Format(ISOLLOW, token, userappId)); ;

                //  Tools.createFile("获取code"+result.ToString());
                OAuthUserInfo os= JsonConvert.DeserializeObject<OAuthUserInfo>(result);
               // OAuthUserInfo os= serializer.Deserialize<OAuthUserInfo>(result); 
                //Tools.createFile(result);
                if (os!=null)
                {
                  if (os.subscribe == 1)
                  {
                      return true;
                  }
                  else {
                      return false;
                  }
               
                }
                else
                {
                    //为了程序正常运行，不抛出错误，可以记录日志
                    return false;
                }
            }
            catch(Exception ex)
            {
                //为了程序正常运行，不抛出错误，可以记录日志
                token = "there_is_an_error_when_getting_token"; Asxsyd92Core.Utils.Tools.createFile(ex.Message);
            }
        
            return false;
        }
        /// <summary>
        /// 获取AccessToken
        /// </summary>
        /// <returns>AccessToken</returns>
        public string GetAccessToken()
        {
    
            
      
            var token = this._cache.GetCache(CACHE_TOKEN_KEY);
            token = null;
            if (token != null)
                return token.ToString();
   

            try
            {
                string result = HttpGet(string.Format(URL_FORMAT_TOKEN, this.appId, this.appSecret));
                //  Tools.createFile(result.ToString());
                // OAuthUserInfo os = .DeserializeObject<OAuthUserInfo>(result);

                var jsonObj = LitJSONCore.JsonMapper.ToObject(result);
                //var carid = jsonData["S_IDCard"].ToString();
               // Dictionary<string, object> jsonObj = JsonConvert.DeserializeObject<dynamic>(result);
              //  Tools.createFile(result);
                if (jsonObj.ContainsKey("access_token"))
                {

                    token = jsonObj["access_token"].ToString();
                    this._cache.SetCache(CACHE_TOKEN_KEY, token.ToString(), 7000);
                    //Tools.createFile(token.ToString());
                }
                else
                {
                    //为了程序正常运行，不抛出错误，可以记录日志
                    token = jsonObj["errmsg"];
                    //Tools.createFile(token.ToString());
                }
            }
            catch(Exception ex)
            {
                Asxsyd92Core.Utils.Tools.createFile(ex.Message);
                //为了程序正常运行，不抛出错误，可以记录日志
                token = "there_is_an_error_when_getting_token";
            }
            //Tools.createFile(token.ToString());
            return token.ToString();
        }

        /// <summary>
        /// 获取ApiTicket
        /// </summary>
        /// <returns>ApiTicket</returns>
        private string GetJsApiTicket()
        {
            var ticket = this._cache.GetCache(CACHE_TICKET_KEY);
           
            if (ticket != null)
                return ticket.ToString();
            try
            {
                string result = HttpGet(string.Format(URL_FORMAT_TICKET, this.GetAccessToken()));

                var jsonObj = LitJSONCore.JsonMapper.ToObject(result);
                //var  jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(result);
              //  Tools.createFile(result);
                if (jsonObj.ContainsKey("ticket"))
                {
                    ticket = jsonObj["ticket"].ToString();
                    this._cache.SetCache(CACHE_TICKET_KEY, ticket.ToString(), 7000);
                }
                else
                {
                    //为了程序正常运行，不抛出错误，可以记录日志
                    ticket = jsonObj["errmsg"];
                  //  Tools.createFile(ticket.ToString());
                }
            }
            catch
            {
                //为了程序正常运行，不抛出错误，可以记录日志
                ticket = "there_is_an_error_when_getting_apiticket";
            }

            return ticket.ToString();
        }
        /// <summary>
        /// 获取jssdk签名配置对象
        /// </summary>
        /// <param name="jsapi">JsApiEnum,如:JsApiEnum.scanQRCode|JsApiEnum.onMenuShareQQ</param>
        /// <returns>微信公众平台JsSdk的配置对象</returns>
        public SignPackage GetSignPackage(JsApiEnum jsapi)
        {
            // HttpContext httpcontext = System.Web.HttpContext.Current;
            // string url = (!string.IsNullOrEmpty(httpcontext.Request.ServerVariables["HTTPS"])) && httpcontext.Request.ServerVariables["HTTPS"] != "off" ? "https://" : "http://";
            // url += httpcontext.Request.ServerVariables["HTTP_HOST"];
            // url += httpcontext.Request.ServerVariables["URL"];
            //// url = Buildurl(url, "id&&time");
            // url += string.IsNullOrEmpty(httpcontext.Request.ServerVariables["QUERY_STRING"]) ? "" : httpcontext.Request.ServerVariables["QUERY_STRING"];

            ///return GetSignPackage(url, jsapi);
            return GetSignPackage("", jsapi);
        }
        #region URL中去除指定参数
        ///
        /// 中去除指定参数
        ///
        /// 地址
        /// 参数
        ///
        public static string Buildurl(string url, string param)
        {
            string url1 = url;
            if (url.IndexOf(param) > 0)
            {
                if (url.IndexOf("&", url.IndexOf(param) + param.Length) > 0)
                {
                    url1 = url.Substring(0, url.IndexOf(param) - 1) + url.Substring(url.IndexOf("&", url.IndexOf(param) + param.Length) + 1);
                }
                else
                {
                    url1 = url.Substring(0, url.IndexOf(param) - 1);
                }
                return url1;
            }
            else
            {
                return url1;
            }
        }
        #endregion
        #region "获取页面url"
        ///
        /// 获取当前访问页面地址参数
        ///
        public  string GetScriptNameQueryString
        {
            get
            {

                return httpContext.HttpContext.Request.Headers["QUERY_STRING"].ToString();
               // return HttpContext.Current.Request.ServerVariables["QUERY_STRING"].ToString();
            }
        }
        ///
        /// 获取当前访问页面地址
        ///
        public  string GetScriptName
        {
            get
            {
                return httpContext.HttpContext.Request.Headers["SCRIPT_NAME"].ToString();
                // return HttpContext.Current.Request.ServerVariables["SCRIPT_NAME"].ToString();
            }
        }
        ///
        /// 获取当前访问页面Url
        ///
        public  string GetScriptUrl
        {
            get
            {
                return GetScriptNameQueryString == "" ? GetScriptName : string.Format("{0}?{1}", GetScriptName, GetScriptNameQueryString);
            }
        }
        ///
        /// 获取当前访问页面 参数
        ///
        public  string GetScriptNameQuery
        {
            get
            {
                return httpContext.HttpContext.Request.Query.ToString();
               // return HttpContext.Current.Request.Url.Query;
            }
        }
        #endregion
        /// <summary>
        /// 获取jssdk签名配置对象
        /// </summary>
        /// <param name="url">当前页面url</param>
        /// <param name="jsapi">JsApiEnum,如:JsApiEnum.scanQRCode|JsApiEnum.onMenuShareQQ</param>
        /// <returns>微信公众平台JsSdk的配置对象</returns>
        public SignPackage GetSignPackage(string url, JsApiEnum jsapi)
        {

            /*
             * 签名字段
           jsapi_ticket=bxLdikRXVbTPdHSM05e5u7OAuJrytndvy8PMBqqgHAqDASw5qjdqMS1R2tQ0Mt-WE06GvKg-Me9-keQE1OOJMA&noncestr=89bdfaab5b3a4e58&timestamp=1497334355&url=http://Asxsyd92Core.wicp.net
             */
            string noncestr = this.CreateNonceStr(16);
            string jsapi_tkcket = this.GetJsApiTicket();
            long timestamp = TimeStamp.Now();
            Dictionary<string, string> signData = new Dictionary<string, string>() { 
                
                {"jsapi_ticket",jsapi_tkcket},{"noncestr",noncestr},
                {"timestamp",timestamp.ToString()},
                {"url",url.ToLower()}
            };

            SignPackage result = new SignPackage()
            {
                appId = this.appId,
                timestamp = timestamp,
                nonceStr = noncestr,
                debug = this._debug,
                signature = new Signature().Sign(signData),
                jsApiList = jsapi.ToString().Replace(" ", "").Split(',')
            };
            return result;
        }

        /// <summary>
        /// 后台发起http请求
        /// </summary>
        /// <param name="url">请求URL</param>
        /// <returns>请求结果字符串</returns>
        private string HttpGet(string url)
        {
            return new WebClient().DownloadString(url);
        }

    }
}